#include "stdafx.h"
#include "mesheditor.h"

namespace Lit
{	
	namespace Editor
	{
		MeshEditor::MeshEditor(QWidget *parent, Qt::WFlags flags)
			: QMainWindow(parent, flags)
		{
			ui.setupUi(this);
			
			mInstance = new Instance( "MeshEditor", this, ui.logDock );
			mInstance->initialise(CoreComponentList() << Lit::COM_SCENEMANAGER << Lit::COM_PHYSICSMANAGER << Lit::COM_CACHEMANAGER, this);

			mProject = new MeshProject( mInstance, ui.meshStructure );

			setupUi();
		}
		MeshEditor::~MeshEditor()
		{
		}
		void MeshEditor::closeEvent( QCloseEvent * evt )
		{
			bool has_proj = mProject && mProject->isCreated();
			bool no_path= mProject->getSavePath().empty();
			if( has_proj )
			{
				if( no_path )
				{
					if( QMessageBox::question( this, "Project Modified", "The current project was not saved, do you want to save now ?", QMessageBox::Yes, QMessageBox::No ) == QMessageBox::Yes )
						mProject->save( );
				}
				else mProject->save( mProject->getSavePath() );
			}
			mInstance->deInitialise(this);
			if( mInstance ) delete mInstance, mInstance = NULL;
			evt->accept();
			QMainWindow::closeEvent( evt );
		}
		void MeshEditor::setupUi()
		{
		}
		void MeshEditor::updateUi( )
		{
			bool c = mProject->isCreated();
			ui.actionSave_Project->setEnabled( c );
			ui.actionImport_Mesh->setEnabled( c );
			ui.actionExport_Mesh->setEnabled( c );
			ui.actionClose_Project->setEnabled( c );
			ui.actionExport_Mesh->setEnabled( c );
			ui.actionImport_Mesh->setEnabled( !c );
			ui.actionCreate_Mesh_Pack->setEnabled( c );
		}

		void MeshEditor::createScene()
		{
			mInstance->getSceneCamera()->setFOVy( Ogre::Degree( 75.0f ) );
			MeshIconDatabase::Instance().initialise(boost::bind( &MeshEditor::meshPreviewCallback, this, _1, _2, _3 ));
			mLight = Lit::Root::SceneManager()->createLight( "", Lit::LT_DIRECTIONAL, Lit::Vec3::ZERO, Lit::Vec3( -0.1, -1, -0.1 ) );

			mWorld = Lit::Root::PhysicsManager()->createWorld();
			mWorld->getDebugger()->setVisible(true);
			MeshDescriptionFilePtr desc(Root::SceneManager()->getMeshDescription("floor.mesh"));
			Physics::BodyPtr b(Lit::Root::SceneManager()->createActor("Floor", desc, mWorld, Lit::Vec3( 100.0f, 0.01f, 100.0f ) ));
			Lit::Root::SceneManager()->setMovableProperties( b->getEntity(), true, b );
			updateUi();

		}
		void MeshEditor::destroyScene()
		{
			if( mLight )
				Lit::Root::SceneManager()->removeLight( mLight->getName() );
			if( mProject ) delete mProject, mProject = NULL;
			MeshIconDatabase::Instance().shutdown();
		}

		void MeshEditor::mouseScrolled( int d )
		{
			if( !mProject->getEntity() ) return;
			Lit::Vec3 entPos( mProject->getEntity()->getPosition() );
			Lit::Vec3 camPos( mInstance->getRenderWidget()->ogreCamera()->getPosition() );
			Lit::Vec3 delta( entPos-camPos );
			if( d < 0 )
			{
				mInstance->getRenderWidget()->ogreCamera()->move( -mInstance->getRenderWidget()->ogreCamera()->getDirection().normalisedCopy()*10.0f );
			}
			else
			{
				if( camPos.z > (entPos.z+mProject->getEntity()->getEntity()->getBoundingRadius()*2.0f) )
					mInstance->getRenderWidget()->ogreCamera()->move( mInstance->getRenderWidget()->ogreCamera()->getDirection().normalisedCopy()*10.0f );
			}
		}
		void MeshEditor::mouseMoved(const QPoint& pos, Qt::MouseButtons btn){
			static QPoint last = pos;
			QPoint delta( pos - last );
			static Lit::Real speed = 20.0f;
			if( btn.testFlag( Qt::RightButton ) )
			{
				mInstance->getSceneCamera()->yaw( Ogre::Degree( ((float)delta.x()) * speed * Lit::Root::Instance().getFrameTime() ) );
				mInstance->getSceneCamera()->pitch( Ogre::Degree( ((float)delta.y()) * speed * Lit::Root::Instance().getFrameTime() ) );
			}
			else if( btn.testFlag( Qt::MidButton ) )
			{
				Lit::Vec3 up(mInstance->getSceneCamera()->getUp());
				Lit::Vec3 right(mInstance->getSceneCamera()->getRight());
				mInstance->getSceneCamera()->move( up * (float)delta.y() * speed * Lit::Root::Instance().getFrameTime() );
				mInstance->getSceneCamera()->move( right * (float)delta.x() * speed * Lit::Root::Instance().getFrameTime() );
			}
			else if( btn.testFlag( Qt::LeftButton ) )
			{
				if(  mProject->getEntity() )
				{
					mProject->getEntity()->getNode()->yaw( Ogre::Degree( ((float)delta.x()) * speed * Lit::Root::Instance().getFrameTime() ) );
					mProject->getEntity()->getNode()->pitch( Ogre::Degree( ((float)delta.y()) * speed * Lit::Root::Instance().getFrameTime() ) );
				}
			}
			last = pos;
		}
		bool MeshEditor::frameStarted( const Ogre::FrameEvent &evt ){
			static Lit::Real speed = 25.0f;
			Lit::Root::Instance().renderOneFrame( evt.timeSinceLastFrame );
			if( Lit::Root::InputManager()->isKeyDown(Key_Z) ) Root::Instance().ogreCamera()->move( Root::Instance().ogreCamera()->getDirection().normalisedCopy() *speed* evt.timeSinceLastFrame );
			if( Lit::Root::InputManager()->isKeyDown(Key_S) ) Root::Instance().ogreCamera()->move( -Root::Instance().ogreCamera()->getDirection().normalisedCopy() * speed*evt.timeSinceLastFrame );
			if( Lit::Root::InputManager()->isKeyDown(Key_Q) ) Root::Instance().ogreCamera()->move( -Root::Instance().ogreCamera()->getRight().normalisedCopy() * speed*evt.timeSinceLastFrame );
			if( Lit::Root::InputManager()->isKeyDown(Key_D) ) Root::Instance().ogreCamera()->move( Root::Instance().ogreCamera()->getRight().normalisedCopy() * speed*evt.timeSinceLastFrame );
			return true;
		}
		
		void MeshEditor::meshPreviewCallback(const std::string &name, size_t current, size_t num_mesh ){
		}
		void MeshEditor::on_actionNew_Project_triggered()
		{
			mProject->create( );
			updateUi();
		}
		void MeshEditor::on_actionOpen_Project_triggered()
		{
			mProject->open( );
			updateUi();
		}
		void MeshEditor::on_actionSave_Project_triggered()
		{
			mProject->save( );
			updateUi();
		}
		void MeshEditor::on_actionImport_Mesh_triggered()
		{
			mProject->importMesh( );
			updateUi();
		}
		void MeshEditor::on_actionExport_Mesh_triggered()
		{
			mProject->exportMesh( );
			updateUi();
		}

		void MeshEditor::on_actionClose_Project_triggered()
		{
			mProject->destroy( );
			updateUi();
		}
		void MeshEditor::on_actionCreate_Mesh_Pack_triggered()
		{
			mProject->createPack( );
		}
		void MeshEditor::on_actionPause_Simulation_triggered( bool state )
		{
			if( mWorld ){
				if( mProject->getBody() )
				{
					mProject->getBody()->setPosition( Lit::Vec3::ZERO );
					if( !mProject->getBody()->isStatic() )
						mProject->getBody()->setInertia( mProject->getBody()->getShape()->calculateInertialMatrix( mProject->getBody()->getMass(), mProject->getBody()->getCollision() ) );
					mProject->getBody()->setFreeState( false );
				}
				Root::PhysicsManager()->renderOneFrame( 0.001 );
				Root::PhysicsManager()->setPaused( !state );
				ui.actionPause_Simulation->setIcon( QIcon( Root::PhysicsManager()->isPaused()?":/Resources/resume.png":":/Resources/stop.png" ) );
				ui.actionPause_Simulation->setText( Root::PhysicsManager()->isPaused()?"Resume Simulation":"Pause Simulation" ) ;
				ui.actionPause_Simulation->setToolTip( Root::PhysicsManager()->isPaused()?"Resume Simulation":"Pause Simulation" ) ;
				LIT_LOG_DBG("Physics Simulation: "+std::string(Root::PhysicsManager()->isPaused()?"paused":"running"));
			}
		}

		void MeshEditor::on_actionDebugger_triggered( bool state )
		{
			if( mWorld ){
				mWorld->getDebugger()->setVisible( state );
				LIT_LOG_DBG("Physics Debugger: "+std::string(mWorld->getDebugger()->isVisible()?"enabled":"disabled"));
			}
		}
			
		void MeshEditor::on_actionPhysics_Options_triggered()
		{
		}
		void MeshEditor::on_actionOptions_triggered()
		{
			Lit::Editor::SettingsDialog::ConfigureOgre(this, mInstance);
		}
	};
};